package org.act.neo4j.temporal.demo;

import org.act.neo4j.temporal.demo.vo.Cross;
import org.act.neo4j.temporal.demo.vo.RelType;
import org.act.neo4j.temporal.demo.vo.RoadChain;
import org.act.neo4j.temporal.demo.vo.TemporalStatus;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by song on 16-1-22.
 */
public class DataImport {

    public static String dbPath = System.getProperty("java.io.tmpdir")+"/neo4j-temporal-demo";
    public static String dataPathNetwork = "/home/song/project/going/neo4j/doc/traffic-data-demo/Topo.csv";
    public static String dataPathDir = "/home/song/project/going/neo4j/doc/traffic-data-demo/";

    static GraphDatabaseService db;

    public static void deleteAllFilesOfDir(File path) {
        if (!path.exists())
            return;
        if (path.isFile()) {
            path.delete();
            return;
        }
        File[] files = path.listFiles();
        for (int i = 0; i < files.length; i++) {
            deleteAllFilesOfDir(files[i]);
        }
        path.delete();
    }

    public static void main(String[] args) throws IOException {

        importNetwork();
        importTemporalData();
        if(db!=null)db.shutdown();
    }

    private static void importTemporalData() throws IOException {
        File dir = new File(dataPathDir);
        File[] files = dir.listFiles();
        List<File> fileList = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            if(files[i].getName().startsWith("TJamData_")){
//                System.out.println(files[i].getName());
                fileList.add(files[i]);
            }
        }
        fileList.sort(null);
        for (int i = 0; i < fileList.size(); i++) {
            System.out.println(fileList.get(i).getName());
        }

        try( Transaction tx = db.beginTx() ) {
            for (int i = 0; i < fileList.size(); i++) {

                int time = Integer.valueOf(fileList.get(i).getName().substring(10, 21));
                System.out.println(fileList.get(i).getName());
                System.out.println(time);
                try (BufferedReader br = new BufferedReader(new FileReader(fileList.get(i)))) {
                    String line;
                    for (int lineCount = 0; (line = br.readLine()) != null; lineCount++) {
                        if (lineCount == 0) continue;
                        TemporalStatus temporalStatus = new TemporalStatus(line);
                        RoadChain roadChain = RoadChain.get(temporalStatus.gridId, temporalStatus.chainId);
                        if (roadChain.getInNum() > 0 && roadChain.getOutNum() > 0) {
                            Relationship relationship = roadChain.getRelationship(db);
                            if (relationship != null) {
                                relationship.setDynProperty("travel-time", time, intToByteArray(temporalStatus.getTravelTime()));
                                relationship.setDynProperty("full-status", time, intToByteArray(temporalStatus.getFullStatus()));
                                relationship.setDynProperty("vehicle-count", time, intToByteArray(temporalStatus.getVehicleCount()));
                                relationship.setDynProperty("segment-count", time, intToByteArray(temporalStatus.getSegmentCount()));
                            } else {
                                System.out.println(roadChain);
                            }
                        } else {
                            continue;
                        }
                    }
                }
            }
            tx.success();
        }
    }


    public static void importNetwork() throws IOException {
        File dir = new File(dbPath);
        System.out.println(dir.getAbsolutePath());
//        System.exit(0);
        if (!dir.exists()){
            dir.mkdir();
        }else{
            deleteAllFilesOfDir(dir);
            dir.mkdir();
        }
        List<RoadChain> roadChainList = new ArrayList<>();
//        System.exit(0);
        db = new GraphDatabaseFactory()
                .newEmbeddedDatabaseBuilder(dir.getAbsolutePath() )
                .loadPropertiesFromFile("")
                .newGraphDatabase();
        try( Transaction tx = db.beginTx() )
        {
            try (BufferedReader br = new BufferedReader(new FileReader(dataPathNetwork))) {
                String line;
                for (int lineCount = 0;(line = br.readLine()) != null;lineCount++) {
                    if(lineCount==0)continue;
//                System.out.println(line);
                    roadChainList.add(new RoadChain(line));
//                if(lineCount>5)break;
                }
                System.out.println("roadChainListSize:"+roadChainList.size());
                int emptyInCount=0;
                int emptyOutCount=0;
                int emptyAllCount=0;
                for (int i=0;i<roadChainList.size();i++){
                    RoadChain roadChain = roadChainList.get(i);
                    roadChain.updateNeighbors();
                    int inCount = roadChain.getInNum();
                    int outCount = roadChain.getOutNum();
                    if(inCount==0 && outCount==0){
                        emptyAllCount++;
                    }else if(inCount==0 && outCount>0){
                        emptyInCount++;
                    }else if(inCount>0 && outCount==0){
                        emptyOutCount++;
                    }else{
                        Cross inCross = Cross.getInCross(roadChain);
                        Cross outCross = Cross.getOutCross(roadChain);
                        Node inNode = db.createNode();
                        Node outNode = db.createNode();
                        inCross.setNode(inNode);
                        outCross.setNode(outNode);
                        Relationship relationship = inNode.createRelationshipTo(outNode, RelType.ROAD_TO);
                        roadChain.setRelationship(relationship);
                    }
//                if(i>5)break;
//                System.out.println(roadChainList.get(i));
                }
//            System.out.println(RoadChain.relationCount);
                System.out.println("borderCount:empty in("+emptyInCount+"),empty out("+emptyOutCount+"),empty all("+emptyAllCount+")");
//                System.out.println(crossList.size());
                System.out.println("Total cross count:"+Cross.getTotalCount());
            }


            tx.success();
        }
    }

    public static final byte[] intToByteArray(int value) {
        return new byte[] {
                (byte)(value >>> 24),
                (byte)(value >>> 16),
                (byte)(value >>> 8),
                (byte)value};
    }
}


//            int emptyInCount=0;
//            int emptyOutCount=0;
//            int emptyAllCount=0;
//            for (int i=0;i<roadChainList.size();i++) {
//                RoadChain roadChain = roadChainList.get(i);
//                //roadChain.updateNeighbors();
//                int inCount = roadChain.getInNum();
//                int outCount = roadChain.getOutNum();
//                if (inCount == 0 && outCount == 0) {
//                    emptyAllCount++;
//                } else if (inCount == 0 && outCount > 0) {
//                    emptyInCount++;
//                } else if (inCount > 0 && outCount == 0) {
//                    emptyOutCount++;
//                } else {
//                    Cross inCross = Cross.getInCross(roadChain);
//                    Cross outCross = Cross.getOutCross(roadChain);
//                    Node inNode = inCross.getNode();
//                    Node outNode = outCross.getNode();
//                    if(inNode==null && outNode==null){
//                        System.out.println(inCross.id+" "+outCross.id);
//                    }else if(inNode==null && outNode!=null){
//                        System.out.println(inCross.id+" "+outCross.id);
//                    }else if(inNode!=null && outNode==null){
//                        System.out.println(inCross.id+" "+outCross.id);
//                    }else {
//                        try {
//                            inNode.createRelationshipTo(outNode, RelType.ROAD_TO);
//                        } catch (NullPointerException e) {
//
//                        }
//                    }
//                }
//            }
//            int edgeCount1=0;
//            int edgeCount=0;
//            int nodeCount=0;
//            for(Cross cross:Cross.crossMap.values()){
//                Node node = db.createNode();
//                node.setProperty("cross-id", cross.id);
//                cross.setNode(node);
//                nodeCount++;
//            }
////            for(Cross cross:crossList) {
////
////            }
//            int emptyInCount=0;
//            int emptyOutCount=0;
//            int emptyAllCount=0;
//            for(RoadChain roadChain:roadChainList){
//                if((roadChain.inChains.size()>0) && (roadChain.outChains.size()>0)){
//                    long inNodeId = Cross.getInCross(roadChain).getNodeId();
//                    long outNodeId = Cross.getOutCross(roadChain).getNodeId();
//                    if(inNodeId==0 && outNodeId==0){
//                        emptyAllCount++;
//                    }else if(inNodeId==0 && outNodeId>0){
//                        emptyInCount++;
//                    }else if(inNodeId>0 && outNodeId==0){
//                        emptyOutCount++;
//                    }else {
//                        Node inNode = Cross.getInCross(roadChain).getNode();
//                        Node outNode = Cross.getOutCross(roadChain).getNode();
//                        edgeCount1++;
//                        if (inNode != null && outNode != null) {
//                            inNode.createRelationshipTo(outNode, RelType.ROAD_TO);
//                            edgeCount++;
//                        }
//                    }
//                }
//            }
//            System.out.println("empty in(" + emptyInCount + "),empty out(" + emptyOutCount + "),empty all(" + emptyAllCount + ")");
//
//            System.out.println("nodeCount:" + nodeCount);
//            System.out.println("edgeCount:" + edgeCount);
//            System.out.println("edgeCount1:" + edgeCount1);